<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Carbon\Carbon;

class UserCoupon extends Model
{
    use HasFactory;

    /**
     * 可批量赋值的属性
     */
    protected $fillable = [
        'user_id',
        'coupon_id',
        'code',
        'status',
        'received_at',
        'used_at',
        'expire_at',
        'order_id',
        'discount_amount',
    ];

    /**
     * 属性类型转换
     */
    protected $casts = [
        'received_at' => 'datetime',
        'used_at' => 'datetime',
        'expire_at' => 'datetime',
        'discount_amount' => 'decimal:2',
    ];

    /**
     * 状态常量
     */
    const STATUS_UNUSED = 'unused';      // 未使用
    const STATUS_USED = 'used';          // 已使用
    const STATUS_EXPIRED = 'expired';    // 已过期

    /**
     * 关联用户
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * 关联优惠券模板
     */
    public function coupon(): BelongsTo
    {
        return $this->belongsTo(Coupon::class);
    }

    /**
     * 关联订单
     */
    public function order(): BelongsTo
    {
        return $this->belongsTo(Order::class);
    }

    /**
     * 作用域：未使用的
     */
    public function scopeUnused($query)
    {
        return $query->where('status', self::STATUS_UNUSED)
            ->where('expire_at', '>', Carbon::now());
    }

    /**
     * 作用域：已使用的
     */
    public function scopeUsed($query)
    {
        return $query->where('status', self::STATUS_USED);
    }

    /**
     * 作用域：已过期的
     */
    public function scopeExpired($query)
    {
        return $query->where(function ($q) {
            $q->where('status', self::STATUS_EXPIRED)
                ->orWhere(function ($subQuery) {
                    $subQuery->where('status', self::STATUS_UNUSED)
                        ->where('expire_at', '<=', Carbon::now());
                });
        });
    }

    /**
     * 作用域：即将过期的（7天内）
     */
    public function scopeExpiringSoon($query)
    {
        $sevenDaysLater = Carbon::now()->addDays(7);
        return $query->where('status', self::STATUS_UNUSED)
            ->where('expire_at', '>', Carbon::now())
            ->where('expire_at', '<=', $sevenDaysLater);
    }

    /**
     * 访问器：是否已过期
     */
    public function getIsExpiredAttribute(): bool
    {
        return $this->status === self::STATUS_EXPIRED ||
            ($this->status === self::STATUS_UNUSED && $this->expire_at && $this->expire_at->lt(Carbon::now()));
    }

    /**
     * 访问器：是否可用
     */
    public function getIsAvailableAttribute(): bool
    {
        return $this->status === self::STATUS_UNUSED &&
            $this->expire_at &&
            $this->expire_at->gt(Carbon::now());
    }

    /**
     * 访问器：剩余天数
     */
    public function getDaysLeftAttribute(): int
    {
        if ($this->is_expired || !$this->expire_at) {
            return 0;
        }

        return max(0, Carbon::now()->diffInDays($this->expire_at, false));
    }

    /**
     * 访问器：状态文本
     */
    public function getStatusTextAttribute(): string
    {
        if ($this->is_expired) {
            return '已过期';
        }

        return match ($this->status) {
            self::STATUS_UNUSED => '未使用',
            self::STATUS_USED => '已使用',
            self::STATUS_EXPIRED => '已过期',
            default => '未知',
        };
    }

    /**
     * 标记为已使用
     *
     * @param int $orderId
     * @param float $discountAmount
     * @return bool
     */
    public function markAsUsed(int $orderId, float $discountAmount): bool
    {
        if ($this->status !== self::STATUS_UNUSED) {
            return false;
        }

        if ($this->is_expired) {
            return false;
        }

        $this->update([
            'status' => self::STATUS_USED,
            'used_at' => Carbon::now(),
            'order_id' => $orderId,
            'discount_amount' => $discountAmount,
        ]);

        // 增加优惠券模板的使用数量
        $this->coupon->incrementUsedQuantity();

        return true;
    }

    /**
     * 标记为过期
     *
     * @return bool
     */
    public function markAsExpired(): bool
    {
        if ($this->status !== self::STATUS_UNUSED) {
            return false;
        }

        $this->update([
            'status' => self::STATUS_EXPIRED,
        ]);

        return true;
    }

    /**
     * 退回优惠券（订单取消时）
     *
     * @return bool
     */
    public function refund(): bool
    {
        if ($this->status !== self::STATUS_USED) {
            return false;
        }

        // 检查是否已过期
        if ($this->expire_at->lt(Carbon::now())) {
            // 已过期，标记为过期
            $this->update([
                'status' => self::STATUS_EXPIRED,
                'order_id' => null,
            ]);
        } else {
            // 未过期，恢复为未使用
            $this->update([
                'status' => self::STATUS_UNUSED,
                'used_at' => null,
                'order_id' => null,
                'discount_amount' => null,
            ]);
        }

        // 减少优惠券模板的使用数量
        $this->coupon->decrementUsedQuantity();

        return true;
    }

    /**
     * 生成唯一的优惠券码
     *
     * @return string
     */
    public static function generateUniqueCode(): string
    {
        do {
            $code = strtoupper(substr(md5(uniqid() . time()), 0, 12));
        } while (self::where('code', $code)->exists());

        return $code;
    }
}
